﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Linq;

namespace MyHttp.helper
{
    public class MyJsonObject
    {
        public enum TYPE_ENUM { TYPE_NULL, TYPE_BOOLEAN, TYPE_NUMBER,
                TYPE_STRING, TYPE_DICTIONARY, TYPE_LIST };

        private TYPE_ENUM objectType;
        private Boolean booleanValue = false;
        private Int32? int32Value = null;
        private UInt32? uint32Value = null;
        private Int64? int64Value = null;
        private UInt64? uint64Value = null;
        private Double? doubleValue = null;
        private Single? floatValue = null;
        private String stringValue;
        private List<Object> listValue;
        private Dictionary<String, Object> dictionaryValue;

        public MyJsonObject(JToken jToken)
        {
            if (jToken is JValue)
            {
                parseJValue(((JValue)jToken).Value);
            }
            else if (jToken is JArray)
            {
                this.objectType = TYPE_ENUM.TYPE_LIST;
                this.listValue = new List<Object>();
                for (JToken temp = ((JArray)jToken).First;
                        null != temp; temp = temp.Next)
                {
                    this.listValue.Add(new MyJsonObject(temp).Value);
                }
            }
            else if (jToken is JObject)
            {
                this.objectType = TYPE_ENUM.TYPE_DICTIONARY;
                this.dictionaryValue = new Dictionary<String, Object>();
                IEnumerable<JProperty> properties =
                            ((JObject)jToken).Properties();
                foreach (JProperty property in properties)
                {
                    DictionaryExtension.AddOrReplace(this.dictionaryValue,
                            property.Name, new MyJsonObject(property.Value).Value);
                }
            }
        }

        private void parseJValue(Object value)
        {
            if (value is UInt64)
            {
                this.objectType = TYPE_ENUM.TYPE_NUMBER;
                if ((UInt64)value > Int64.MaxValue)
                {
                    this.uint64Value = (UInt64)value;
                }
                else if ((UInt64)value > UInt32.MaxValue)
                {
                    this.int64Value = Convert.ToInt64((UInt64)value);
                }
                else if ((UInt64)value > Int32.MaxValue)
                {
                    this.uint32Value = Convert.ToUInt32((Int64)value);
                }
                else
                {
                    this.int32Value = Convert.ToInt32((Int64)value);
                }
            }
            else if (value is Int64)
            {
                this.objectType = TYPE_ENUM.TYPE_NUMBER;
                if ((Int64)value > UInt32.MaxValue)
                {
                    this.int64Value = (Int64)value;
                }
                else if ((Int64)value > Int32.MaxValue)
                {
                    this.uint32Value = Convert.ToUInt32((Int64)value);
                }
                else
                {
                    this.int32Value = Convert.ToInt32((Int64)value);
                }
            }
            else if (value is Single)
            {
                this.objectType = TYPE_ENUM.TYPE_NUMBER;
                this.floatValue = (Single)value;
            }
            else if (value is Double)
            {
                this.objectType = TYPE_ENUM.TYPE_NUMBER;
                this.doubleValue = (Double)value;
            }
            else if (value is String)
            {
                this.objectType = TYPE_ENUM.TYPE_STRING;
                this.stringValue = (String)value;
            }
            else if (value is Boolean)
            {
                this.objectType = TYPE_ENUM.TYPE_BOOLEAN;
                this.booleanValue = (Boolean)value;
            }
        }

        public Object Value
        {
            get
            {
                if (TYPE_ENUM.TYPE_NULL == objectType) return null;
                if (TYPE_ENUM.TYPE_BOOLEAN == objectType) return booleanValue;
                if (TYPE_ENUM.TYPE_STRING == objectType) return stringValue;
                if (TYPE_ENUM.TYPE_DICTIONARY == objectType) return dictionaryValue;
                if (TYPE_ENUM.TYPE_LIST == objectType) return listValue;
                if (int32Value.HasValue) return int32Value;
                if (uint32Value.HasValue) return uint32Value;
                if (int64Value.HasValue) return int64Value;
                if (uint64Value.HasValue) return uint64Value;
                if (floatValue.HasValue) return floatValue;
                return doubleValue;
            }
        }
    }
}
